#!/usr/bin/env python
# This Python file uses the following encoding: utf-8

import sys
import os
import subprocess
import mutagen
from optparse import OptionParser
import shutil
import ConfigParser

class Singleton(object):
  _instances = {}
  def __new__(class_, *args, **kwargs):
    if class_ not in class_._instances:
        class_._instances[class_] = super(Singleton, class_).__new__(class_, *args, **kwargs)
    return class_._instances[class_]

class Options(Singleton):
    def __init__(self):
        self.cmd='None'
        self.root_dir='None'
             
    def get_input_root_dir(self):
        return self.root_dir
    
    def set_input_root_dir(self,inputfile):
        if os.path.isdir(inputfile):
            self.root_dir=inputfile
        else:
            self.root_dir=os.path.dirname(inputfile)
       
    
'''

'''
class Setup(Singleton):        
    APPLICATION_NAME = "audio_converter"
    SETTINGS_FILE_NAME = "settings.cfg"
    DEFAULT_CONFIG_NAME="default.cfg"
    config='NONE'
    
    def getApplicationName(self):
        return self.APPLICATION_NAME
    
    def get_default_config_name(self):
        return self.DEFAULT_CONFIG_NAME
    
    
    def getHomeDir(self):
        platform = sys.platform
        print 'your  platform is %s' % (platform,)
        if ('win32' in platform):
            home = os.environ.get("APPDATA")
        else:
            home = os.environ.get("HOME")
        print 'home is %s' % (home,)
        homeAppDir = home + os.sep +".config"+os.sep+ self.getApplicationName()
        if not os.path.exists(homeAppDir):
            os.makedirs(homeAppDir)
        return homeAppDir
    def get_config(self):
        if self.config=='NONE':
            rc_file = self.getHomeDir() + os.sep + self.SETTINGS_FILE_NAME
            if not os.path.exists(rc_file):
                print "config file does not exist"
                self.load_default_config(rc_file)
                print "User config was created in the :"+rc_file
            assert os.path.exists(rc_file),"Failed to create default config: "+rc_file
            print "User config was loaded :"+rc_file
            self.config=ConfigParser.ConfigParser()
            self.config.read(rc_file)
        return self.config
    
    def get_keys(self,section):
        print "get keys for section "+section.upper()
        keys=self.get_config().options(section.upper()) 
        return keys
    def get_value(self,section,key):
        value=self.get_config().get(section.upper(),key)
        return value
    def get_boolean_value(self,section,key):
        value=self.get_config().getboolean(section.upper(),key)
        return value
    
    def owerwrite_user_config(self):
        rc_file = self.getHomeDir() + os.sep + self.SETTINGS_FILE_NAME
        self.load_default_config(rc_file)
        print "User config "+rc_file+" was owerwritten with default config"
    
    def load_default_config(self,dest_config):      
        pathname = os.path.dirname(sys.argv[0])
        default_config=pathname+os.sep+self.DEFAULT_CONFIG_NAME
        assert os.path.exists(default_config),"Failed to found default config: "+default_config
        shutil.copyfile(default_config,dest_config)
        
    def create_default_configfile(self,file_path):
        import ConfigParser
        config = ConfigParser.ConfigParser()
        config.add_section("MP3")
        config.set("MP3","default_codec","test_ffmpeg")
        with open(file_path, 'w') as configfile:    # save
                config.write(configfile)

class Converter():
     #options=''
    def __init__(self):
        self.config='None'
        import formats
        from formats.cue import CUE
        from formats.flac import FLAC
        from formats.mp3 import MP3
        self.types=[CUE,FLAC,MP3]
        self.setup=Setup()
        
        
        
    def get_supported_file_types(self):
        supported_types=[]
        for type in self.types:
            supported_types.append(type.__name__)            
        return supported_types
    
    
    def get_input_file_type(self,file_name):
        file_extention=os.path.splitext(file_name)[1].replace(".","")
        kind="None"
        for Kind in self.types:
            if Kind.get_file_type().upper()==file_extention.upper():
                kind=Kind()
                return kind
        assert kind!="None"    
        return kind
                 
    
    def get_output_file_type(self):
        output_extention=self.get_output_extention()
        kind="None"
        for Kind in self.types:
            print Kind.get_file_type().upper()+"=="+output_extention.upper()
            if Kind.get_file_type().upper()==output_extention.upper():
                print "Output file type is "+str(Kind.get_file_type().upper()) 
                kind=Kind()
                return kind
        assert kind!="None"    
        return kind
        return kind
        
    def is_type_supported(self,file_type):
        if file_type.upper() in self.get_supported_file_types():
            print (file_type +" is supported")
            return True
        return False
     
            
 #   def set_output_extention(self):
 #       self.output_extention=self.get_opts().cmd.outputformat
  #  
  #  def get_output_extention(self):
  #      return  self.output_extention
        
    def find_files(self,root_dir,extention):
        files = list()
        files.extend([os.path.join(root_dir, d) for d in os.listdir(root_dir) if d.lower().endswith("."+extention) and not os.path.isdir(d)])
        subdirs = [os.path.join(root_dir, d) for d in os.listdir(root_dir) if os.path.isdir(os.path.join(root_dir, d))]
        for subdir in subdirs:
            files.extend(self.find_files(subdir))
        return files
 
                
    def get_default_output_format(self):
        return "MP3"
    
    def convert_single_file(self,file_name):
        new_file=file_name.replace(self.get_input_root_dir(),self.options.outputdir)
        new_dir=os.path.dirname(new_file)
        #recursively created needed directory structure
        if not os.path.exists(new_dir):
            os.makedirs(new_dir)
        os.chdir(new_dir)
        input_format=self.get_input_file_type(file_name)
        outpuf_format=self.get_output_file_type()
        
        kwargs={"output_format":outpuf_format}
        input_format.process_file(file_name,**kwargs)
        return_code = 0
        sys.exit()
        return_code = subprocess.call(cmd, shell=1)
        # Stop process if splitting failed
        if return_code!=0:
                return
        
        
        return ""
    
    
    def process_files(self):
        files=list()
        if os.path.isfile(self.get_opts().cmd.inputfile): 
            files.extend([self.get_opts().cmd.inputfile])
        if os.path.isdir(self.get_opts().cmd.inputfile): 
            files=self.find_files(self.get_opts().get_input_root_dir(),self.get_opts().cmd.inputextention )
        for single_file in files:
            self.convert_single_file(single_file)
    
    def get_opts(self):
        return Options()
          
    def do_config(self):
        if self.get_opts().cmd.cleanconfig:
            self.setup.owerwrite_user_config()

    def parseOptions(self):
        parser = OptionParser()
        parser.add_option("-i", "--inputfile", dest="inputfile", help="Audio file or directory you want to convert")
        parser.add_option("-e", "--ext", dest="inputextention", help="Extention of Audio file you want to convert. Has to be used when directory specified as input.\nSeveral extentions could be specified using ; delimiter")
        parser.add_option("-d", "--outputdir", dest="outputdir", help="Output directory to save converted files.")
        parser.add_option("-o", "--ouputformat", dest="outputformat", help="Output format audio files will be converted. Supported are: "+str(self.get_supported_file_types()))
        parser.add_option("-c", "--cleanconfig",action="store_true",dest="cleanconfig", help="Overwrites user config with default config")
        (self.get_opts().cmd, args) = parser.parse_args()
        if not self.get_opts().cmd.inputfile:
            print ("ERROR:: you didn't specify input file or directory!\n")
            print ("Usage for "+str(parser.get_option("-i"))+" : "+parser.get_option("-i").help)
            sys.exit()
        #go here when user specified directory , but forgot to specify extention of input files to search 
        if (os.path.isdir(self.get_opts().cmd.inputfile) and not self.get_opts().cmd.inputextention):
            print ("ERROR:: you didn't specify input file extention!\n")
            print ("Usage for "+str(parser.get_option("-e"))+" : "+parser.get_option("-e").help)
            sys.exit()
        
        if not self.get_opts().cmd.outputformat:
            print ("you didn't specify output format. Default will be used  "+self.get_default_output_format())
            self.get_opts().cmd.outputformat=self.get_default_output_format()
        inputfile=self.get_opts().cmd.inputfile
        self.get_opts().set_input_root_dir(inputfile)
        if not self.get_opts().cmd.outputdir:
            print ("you didn't specify output directory. All files including original  file structure will be saved  under root dir \n"+self.get_opts().root_dir)
            self.get_opts().cmd.outputdir=self.get_opts().root_dir
            self.get_opts().cmd.outputformat=self.get_default_output_format()
            
    
        if not self.is_type_supported(self.get_opts().cmd.outputformat):
            print ("Output format "+self.get_opts().cmd.outputformat+" is not supported")
            print ("Usage for "+str(parser.get_option("-o"))+" : "+parser.get_option("-o").help)
            sys.exit()
        
        if (self.get_opts().cmd.inputfile):
            if os.path.isfile(self.get_opts().cmd.inputfile):
                #when user specified single file set it extention to variable for compatibility
                self.get_opts().cmd.inputextention=os.path.splitext(self.get_opts().cmd.inputfile)[1]
                print ("Input file selected for convert:"+str(self.get_opts().cmd.inputfile)+"\nFile type is "+self.get_opts().cmd.inputextention)
            if os.path.isdir(self.get_opts().cmd.inputfile):
                print ("Input directory selected for convert: "+str(self.get_opts().cmd.inputfile)+"\n"+"All files found inside will be converted recursively")
                
        if (self.get_opts().cmd.cleanconfig):
                print "user config will be owerwritten with default config"

if __name__ == "__main__":
    converter=Converter()
    converter.parseOptions()
    converter.do_config()
    #sys.exit()
    converter.process_files()
    #converter.main()
